package org.embedchat.server.service;

import org.embedchat.database.ChatRoomDAOInterface;
import org.embedchat.database.DAOFactoryInterface;
import org.embedchat.database.DatabaseProvider;
import org.embedchat.database.ItemNotFoundException;
import org.embedchat.database.UserDAOInterface;
import org.embedchat.entity.ChatRoom;
import org.embedchat.entity.User;
import org.embedchat.protocol.message.client.LoginMessage;
import org.embedchat.protocol.message.client.RoomsListRequestMessage;
import org.embedchat.protocol.message.common.TextMessage;
import org.embedchat.protocol.message.server.ErrorMessage;
import org.embedchat.protocol.message.server.RoomsListMessage;
import org.embedchat.protocol.message.server.UsersListMessage;
import org.embedchat.server.live.OnlineChatRoom;
import org.embedchat.server.live.OnlineUser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.common.IoSession;

import java.util.ArrayList;
import java.util.List;

/**
 * @author koba
 */
public class ChatEngine {

    private Log log = LogFactory.getLog(ChatEngine.class);

    private List<OnlineChatRoom> onlineRooms = new ArrayList<OnlineChatRoom>();
    private DAOFactoryInterface factory = DatabaseProvider.getInstance().getDAOFactory();

    public ChatEngine() {
    	log.debug("ChatEngine()");
    }
    /**
     * 1) Validate user exists in database and get this user
     * 2) Validate user not logged
     * 3) Activate room, if not alredy activated
     * 4) Add user to this room
     * 5) Return to user list with all uders of this room
     * 
     * @param session  the IoSession
     * @param loginMessage  the LoginMessage
     */
    public void processLogin(IoSession session, LoginMessage loginMessage) {
        UserDAOInterface userDAO = factory.getUserDAO();
        ChatRoomDAOInterface chatRoomDAO = factory.getChatRoomDAO();        
    	log.debug("processLogin: " + loginMessage);
    	// 1) 
    	User user;
		try {
			user = userDAO.findUser(loginMessage.getLogin(), loginMessage.getPassword());
		} catch (ItemNotFoundException e1) {
			ErrorMessage error = new ErrorMessage();
			error.setErrorMessageString("Bad user login or password");
			error.setMessageCode(ErrorMessage.BAD_REQUEST_ERROR);
			session.write(error);
			return;
		}
    	// 2)
    	for (OnlineChatRoom room : onlineRooms) {
    		if (room.isUserPresent(user)) {
				ErrorMessage error = new ErrorMessage();
				error.setErrorMessageString("User alredy logged in room: "
						+ room.getRoom().getName());
				error.setMessageCode(ErrorMessage.LOGIC_ERROR);
				session.write(error);
				return;
    		}
    	}
    	
    	// 3)
    	OnlineChatRoom userRoom = null;
    	for (OnlineChatRoom room : onlineRooms) {
    		log.debug("Online room id: " + room.getRoom().getId());
    		log.debug("Login message id: " + loginMessage.getRoomId());
    		if (room.getRoom().getId().intValue() == loginMessage.getRoomId()) {
    			log.debug("User room alredy online");
    			userRoom = room;	
    		}
    	}
    	if (userRoom == null) {
    		ChatRoom room;
			try {
				room = chatRoomDAO.findChatRoom((long) loginMessage.getRoomId());
				log.debug("Room loaded from database");				
			} catch (ItemNotFoundException e) {
    			ErrorMessage error = new ErrorMessage();
    			error.setErrorMessageString("Room with [" + loginMessage.getRoomId() + "] not found");
    			error.setMessageCode(ErrorMessage.LOGIC_ERROR);
    			session.write(error);
    			return;
			}
    		userRoom = new OnlineChatRoom(room);
    		onlineRooms.add(userRoom);
    	}
    	
    	// 4)
    	userRoom.addUser(session, user);
    	
    	// 5)
    	UsersListMessage usersList = new UsersListMessage();
    	for (OnlineUser roomUser: userRoom.getOnlineUsers()) {
    		log.debug("roomUser id: " + roomUser.getUser().getId());
    		log.debug("roomUser login: " + roomUser.getUser().getLoginName());
    		usersList.addUser(roomUser.getUser().getId().intValue(), roomUser.getUser().getLoginName());
    	}
    	
    	for (IoSession userSession: userRoom.getOnlineUsersSessions()) {
    		userSession.write(usersList);
    	}
    }
    
    public void processTextMessage(IoSession session, TextMessage message) {
    	boolean allOk = false;
    	for (OnlineChatRoom room : onlineRooms) {
    		if (room.isSessionPresent(session)) {
    			allOk = true;
    			message.setUserId(room.getUser(session).getUser().getId().intValue());
    			for (IoSession usersSession : room.getOnlineUsersSessions()) {
    				usersSession.write(message);
    			}
    		}
    	}
    	if(!allOk) {
			ErrorMessage error = new ErrorMessage();
			error.setErrorMessageString("Try to login first");
			error.setMessageCode(ErrorMessage.LOGIC_ERROR);
			session.write(error);
    	}
    }

	public void processRoomsListMessage(IoSession session, RoomsListRequestMessage message) {
	    ChatRoomDAOInterface chatRoomDAO = factory.getChatRoomDAO();
		RoomsListMessage response = new RoomsListMessage();
		List<ChatRoom> availableRooms = chatRoomDAO.findAll();
		for (ChatRoom room : availableRooms) {
			response.addRoom(room.getId().intValue(), room.getName());
		}
		session.write(response);
	}
	
	public void processExit(IoSession session) {
    	for (OnlineChatRoom room : onlineRooms) {
    		if (room.isSessionPresent(session)) {
    			room.removeUser(session);
    		}
        	UsersListMessage usersList = new UsersListMessage();
        	for (OnlineUser roomUser: room.getOnlineUsers()) {
        		usersList.addUser(roomUser.getUser().getId().intValue(), roomUser.getUser().getLoginName());
        	}
        	for (IoSession userSession: room.getOnlineUsersSessions()) {
        		userSession.write(usersList);
        	}

    	}
	}
}


